/**
 * @attention 仅适用于dgm v2.0
 */

#ifndef DRV_DGM_H
#define DRV_DGM_H

#include "fdcan.h"

/**
 * @brief dgm命令索引值枚举
 */
typedef enum
{
    DGM_CMD_MOTOR_DISABLE = 0, // 停止电机, 无发送数据, 返回int32_t(执行结果)
    DGM_CMD_MOTOR_ENABLE,      // 使能电机, 无发送数据, 返回int32_t(执行结果); 注意如果dgm已使能, 则会返回执行失败(-1)

    DGM_CMD_SET_TORQUE,   // 设置电机目标转矩, 发送float(N·m), 无返回数据
    DGM_CMD_SET_VELOCITY, // 设置电机目标转速, 发送float(r/s), 无返回数据
    DGM_CMD_SET_POSITION, // 设置电机目标位置, 发送float(r), 无返回数据
    DGM_CMD_SYNC,         // 运动控制指令同步信号, 无发送数据, 无返回数据

    DGM_CMD_SET_HOME = 12,     // 把当前位置设置为零点, 无发送数据, 返回int32_t(执行结果)
    DGM_CMD_ERROR_RESET,       // 清除错误代码, 无发送数据, 返回int32_t(执行结果)
    DGM_CMD_GET_STATUSWORD,    // 获取当前状态和错误信息, 无发送数据, 返回uint32_t(状态信息)和uint32_t(错误信息)
    DGM_CMD_STATUSWORD_REPORT, // dgm内部状态和错误信息发生变化时的报文, 主动上报uint32_t(状态信息)和uint32_t(错误信息)

    DGM_CMD_GET_TORQUE,   // 获取当前电机实际转矩, 无发送数据, 返回float(N·m)
    DGM_CMD_GET_VELOCITY, // 获取当前电机实际转速, 无发送数据, 返回float(r/s)
    DGM_CMD_GET_POSITION, // 获取当前电机实际位置, 无发送数据, 返回float(r)
    DGM_CMD_GET_I_Q,      // 获取当前电机电流, 无发送数据, 返回float(A)
    DGM_CMD_GET_VBUS,     // 获取当前母线电压, 无发送数据, 返回float(V)
    DGM_CMD_GET_IBUS,     // 获取当前母线电流, 无发送数据, 返回float(A)
    DGM_CMD_GET_POWER,    // 获取当前电机功率, 无发送数据, 返回float(W)

    DGM_CMD_HEARTBEAT = 63, // 心跳, 可以由用户控制器发送也可以由dgm发送, 无发送数据, 无返回数据
} DgmCmdIndex_t;

/**
 * @brief dgm状态枚举
 */
typedef enum
{
    DGM_DISABLE = 0, // 失能
    DGM_ENABLE,      // 使能
    DGM_ERROR        // 错误
} DgmStatus_t;

/**
 * @brief dgm实例结构体
 */
typedef struct
{
    uint8_t id;                  // 节点ID
    DgmStatus_t status;          // 状态
    FDCAN_HandleTypeDef *hfdcan; // fdcan句柄
} Dgm_t;

/**
 * @brief dgm状态字消息结构体
 */
typedef struct
{
    uint8_t id;
    uint32_t state;
    uint32_t error;
} DgmStatuswordMsg_t;

/**
 * @brief 初始化一个dgm实例
 * @param dgm: dgm实例
 * @param id: 节点ID
 * @param hfdcan: fdcan句柄
 * @retval None
 */
void DGM_Init(Dgm_t *dgm, uint8_t id, FDCAN_HandleTypeDef *hfdcan);

/**
 * @brief 发送无数据的dgm指令
 * @param dgm: dgm实例
 * @param cmd: 指令
 * @retval None
 */
void DGM_SendCmdWithoutData(Dgm_t *dgm, DgmCmdIndex_t cmd);

/**
 * @brief 发送float数据的dgm指令
 * @param dgm: dgm实例
 * @param cmd: 指令
 * @param data: 数据
 * @retval None
 */
void DGM_SendCmdWithFloat(Dgm_t *dgm, DgmCmdIndex_t cmd, float data);

#endif //DRV_DGM_H
